package com.example.xuwsh.redis;


import com.example.xuwsh.constant.Constants;
import com.example.xuwsh.exception.GlobalException;
import redis.clients.jedis.Jedis;

import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

/**
 * @Author: xuwsh
 * @Date: 2023/04/18/16:00
 * @Description:
 */
public class XuwshRedisTool extends XuwshRedisConfig {

    public XuwshRedisTool() {
    }

    public String set(final String key, final String value) {
        return execute(key, jedis -> jedis.set(key, value));
    }

    /**
     * 设置键的过期时间为 second 秒
     *
     * @param key
     * @param value
     * @return
     */
    public String setEx(final String key, final String value, long second) {
        return execute(key, new XuwshRedisExecutor<String>() {
            @Override
            public String execute(Jedis jedis) {
                return jedis.setex(key, second, value);
            }
        });
    }

    /**
     * 设置键的过期时间为 mills 毫秒
     *
     * @param key
     * @param value
     * @param mills
     * @return
     */
    public String setPx(final String key, final String value, long mills) {
        return execute(key, new XuwshRedisExecutor<String>() {
            @Override
            public String execute(Jedis jedis) {
                return jedis.psetex(key, mills, value);
            }
        });
    }

    /**
     * 只在键不存在时，才对键进行设置操作
     *
     * @param key
     * @param value
     * @return
     */
    public Long setNx(final String key, final String value) {
        return execute(key, new XuwshRedisExecutor<Long>() {
            @Override
            public Long execute(Jedis jedis) {
                return jedis.setnx(key, value);
            }
        });
    }

    public String get(final String key) {
        return execute(key, new XuwshRedisExecutor<String>() {
            @Override
            public String execute(Jedis jedis) {
                return jedis.get(key);
            }
        });
    }

    public Boolean exists(final String key, XuwshRedisExecutor<Boolean> XuwshRedisExecutor) {
        return execute(key, new XuwshRedisExecutor<Boolean>() {
            @Override
            public Boolean execute(Jedis jedis) {
                return jedis.exists(key);
            }
        });
    }

    public Long expire(final String key, final int seconds) {
        return execute(key, new XuwshRedisExecutor<Long>() {
            @Override
            public Long execute(Jedis jedis) {
                return jedis.expire(key, seconds);
            }
        });
    }

    public Long incr(final String key) {
        return execute(key, new XuwshRedisExecutor<Long>() {
            @Override
            public Long execute(Jedis jedis) {
                return jedis.incr(key);
            }
        });
    }

    public Long decr(final String key) {
        return execute(key, new XuwshRedisExecutor<Long>() {
            @Override
            public Long execute(Jedis jedis) {
                return jedis.decr(key);
            }
        });
    }

    public Long hset(final String key, final String field, final String value) {
        return execute(key, new XuwshRedisExecutor<Long>() {
            @Override
            public Long execute(Jedis jedis) {
                return jedis.hset(key, field, value);
            }
        });
    }

    public String hget(final String key, final String field) {
        return execute(key, new XuwshRedisExecutor<String>() {
            @Override
            public String execute(Jedis jedis) {
                return jedis.hget(key, field);
            }
        });
    }

    public String hmset(final String key, final Map<String, String> hash) {
        return execute(key, new XuwshRedisExecutor<String>() {
            @Override
            public String execute(Jedis jedis) {
                return jedis.hmset(key, hash);
            }
        });
    }

    public List<String> hmget(final String key, final String... fields) {
        return execute(key, new XuwshRedisExecutor<List<String>>() {
            @Override
            public List<String> execute(Jedis jedis) {
                return jedis.hmget(key, fields);
            }
        });
    }

    public Long del(final String key) {
        return execute(key, new XuwshRedisExecutor<Long>() {
            @Override
            public Long execute(Jedis jedis) {
                return jedis.del(key);
            }
        });
    }

    public Map<String, String> hgetAll(final String key) {
        return execute(key, new XuwshRedisExecutor<Map<String, String>>() {
            @Override
            public Map<String, String> execute(Jedis jedis) {
                return jedis.hgetAll(key);
            }
        });
    }

    /**
     * 判断key是否存在
     *
     * @param key
     * @param value
     * @return
     */
    public boolean sismember(final String key, final String value) {
        return exists(key, new XuwshRedisExecutor<Boolean>() {
            @Override
            public Boolean execute(Jedis jedis) {
                return jedis.sismember(key, value);
            }
        });
    }

    public void handleWithLock(String key, Consumer<RedisLockToolParams> handleConsumer, Consumer<RedisLockToolParams> lockFailConsumer) {
        handleWithLock(RedisLockToolParams.create(key), handleConsumer, lockFailConsumer);
    }

    public void handleWithLock(RedisLockToolParams params, Consumer<RedisLockToolParams> handleConsumer, Consumer<RedisLockToolParams> lockFailConsumer) {

        boolean lock = false;
        try {
            String s = setEx(params.getKey(), "0", params.getTime());
            if (Constants.OK.equals(s)) {
                lock = Boolean.TRUE;
            }
        } catch (Exception e) {
            throw new GlobalException("服务器异常");
        }
        /**
         * 加锁失败
         */
        if (!lock) {
            lockFailConsumer.accept(params);
            return;
        }

        /**
         * 加锁成功处理
         */
        try {
            handleConsumer.accept(params);
        } catch (Exception e) {
            throw new GlobalException(e.getMessage());
        } finally {
            if (params.needAutoUnLock()) {
                try {
                    del(params.getKey());
                } catch (Exception e) {
                    throw new GlobalException(e.getMessage());
                }
            }
        }
    }

}
